/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gcalscraper.wapo.date;

import gcalscraper.wapo.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author dave
 */
public class DateParser {
  
  private Calendar today;
  private SimpleDateFormat sdf2a;
  private SimpleDateFormat sdf2b;
  
  public DateParser() {
    today = new GregorianCalendar();
    sdf2a = new SimpleDateFormat("h a EEEE, MMM. d");
    sdf2b = new SimpleDateFormat("h:mm a EEEE, MMM. d");
  }
  
  public List<Occurrence> parse(Event e) {
    
    String dateSpec = e.getDetailedDateTime();
    
    if (dateSpec == null) {
      Logger.getAnonymousLogger().warning("No detailed date info for " + e);
      return new LinkedList<Occurrence>();
    }
    
    if (dateSpec.contains("\n")) {
      List<Occurrence> answer = new LinkedList<Occurrence>();    
      String[] ds = dateSpec.split("\n");
      
      for (int i = 0; i < ds.length; i++) {
        List<Occurrence> a2 = parseOneString(ds[i]);
        for (Occurrence o : a2)
          answer.add(o);        
      }
      return answer;
    } else {
      return parseOneString(dateSpec);
    }
  }
  
  public List<Occurrence> parseOneString(String dateSpec) {
    List<Occurrence> answer = new LinkedList<Occurrence>();
    
    Occurrence o = trySimpleParse1(dateSpec, sdf2a);
    if (o != null) {
      answer.add(o);
      return answer;      
    }

    o = trySimpleParse1(dateSpec, sdf2b);
    if (o != null) {
      answer.add(o);
      return answer;      
    }

    o = trySimpleParse2(dateSpec);
    if (o != null) {
      answer.add(o);
      return answer;      
    }

    o = tryTimeRange(dateSpec);
    if (o != null) {
      answer.add(o);
      return answer;      
    }

    List<Occurrence> os = tryTimeSeries(dateSpec);    

    if (os.size() > 0) {
      for (Occurrence o2 : os) 
        answer.add(o2);
      return answer;
    }

    os = trySeveralDays(dateSpec);    
    if (os.size() > 0) {
      for (Occurrence o2 : os) 
        answer.add(o2);
      return answer;
    }
    
    return answer;
  } 
  
  private Occurrence trySimpleParse1(String e, SimpleDateFormat sdf) {
    try {
      Date p = sdf.parse(e);
      return Occurrence.createFrom(today, p);
    } catch (Exception ex) {
    }
    return null;
  }
  
  private Date trySimpleParsers(String d) {
    SimpleDateFormat[] sdfs = new SimpleDateFormat[] {sdf2a, sdf2b};
    
    for (int i = 0; i < sdfs.length; i++) {
      try {
        return sdfs[i].parse(d);
      } catch (Exception ex) {
      }
    }
    
    return null;
  }
  
  private Pattern timeRangePattern = Pattern.compile(".*([0-9][0-9]?(:[0-9][0-9])?)[^0-9]*-[^0-9]*([0-9][0-9]?(:[0-9][0-9])?)(.*)");
    
  private Occurrence tryTimeRange(String e) {
    Matcher m = timeRangePattern.matcher(e);
    
    if (m.matches()) {     
      String a = m.group(1) + m.group(5);
      String b = m.group(3) + m.group(5);
      
      Date start = null;
      Date end = null;
      try {
        start = sdf2a.parse(a);
      } catch (Exception ex) {
        try {
          start = sdf2b.parse(a);
        } catch (Exception ex2) {
        }
      }
      
      try {
        end = sdf2a.parse(b);
      } catch (Exception ex) {
        try {
          end = sdf2b.parse(b);
        } catch (Exception ex2) {
        }
      }
      
      if (start != null && end != null)
        return Occurrence.createFrom(today, start, end);      
    }   
    
    return null;
  }
  
  private Pattern timeSeriesPattern = Pattern.compile(".*([0-9][0-9]?(:[0-9][0-9])?)[^0-9]*and[^0-9]*([0-9][0-9]?(:[0-9][0-9])?)(.*)");
  
  private List<Occurrence> tryTimeSeries(String e) {
    List<Occurrence> answer = new LinkedList<Occurrence>();
    
    Matcher m = timeSeriesPattern.matcher(e);
    
    if (m.matches()) {     
      /*for (int i = 0; i <= m.groupCount(); i++) {
        System.out.println("matching group " + i + " = " + m.group(i));
      }*/
      String a = m.group(1) + m.group(5);
      String b = m.group(3) + m.group(5);
      
      Date first = trySimpleParsers(a);
      Date second = trySimpleParsers(b);
      
      if (first != null && second != null) {
        answer.add(Occurrence.createFrom(today, first));
        answer.add(Occurrence.createFrom(today, second));
      }
    }
    
    return answer;
  }
  
  private SimpleDateFormat sdf3 = new SimpleDateFormat("EEEE, MMM. d");
  private Occurrence trySimpleParse2(String e) {
    
    try {
      Date parsed = sdf3.parse(e);
      
      return Occurrence.createAllDayFrom(today, parsed);
    } catch (Exception ex) {
    }
    return null;
  }
  
  // 8 PM Friday-Saturday, Jan. 18-19
  private Pattern timeRangePattern2 = 
      Pattern.compile("[^0-9]*([0-9][0-9]?(:[0-9][0-9])?)[^AP]*(AM|PM).*"
  //(AM)|(PM)"
      + ".*([A-Z][a-z]+)-([A-Z][a-z]+).*([A-Z][a-z]+\\.)[^0-9]*([0-9]+)[^0-9]*-[^0-9]*([0-9]+)");
  private List<Occurrence> trySeveralDays(String e) {
    List<Occurrence> answer = new LinkedList<Occurrence>();
    
    Matcher m = timeRangePattern2.matcher(e);
    if (m.matches()) {
      /*for (int i = 0; i <= m.groupCount(); i++) {
        System.out.println("matching group " + i + " = " + m.group(i));
      }*/
      String a = m.group(1) + " " + m.group(3) + " " + m.group(4) + ", "
          + m.group(6) + " " + m.group(7);
      String b = m.group(1) + " " + m.group(3) + " " + m.group(5) + ", "
          + m.group(6) + " " + m.group(8);
    
      Date start = trySimpleParsers(a);
      Date end = trySimpleParsers(b);
      
      Date i = (Date) start.clone();
      Calendar c = Calendar.getInstance();
      while (i.compareTo(end) <= 0) {
        answer.add(Occurrence.createFrom(today, i));
        c.setTime(i);
        c.add(Calendar.DAY_OF_MONTH, 1);
        i = c.getTime();
      }
    }
    
    return answer;
  }
}
